﻿using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using System.Text;

namespace Faml.Frontend
{
  
    public class FamlConditionalExpression : FamlExpression
    {
        private FamlExpression condition;
        private FamlExpression trueBranch;
        private FamlExpression falseBranch;

        public FamlConditionalExpression(FamlExpression condition,FamlExpression trueBranch, FamlExpression falseBranch)
        {
            this.condition = condition;
            this.trueBranch = trueBranch;
            this.falseBranch = falseBranch;
            MakeMetadata();
        }

        public FamlExpression Condition
        {
            get
            {
                return condition;
            }
        }

        public FamlExpression TrueBranch
        {
            get
            {
                return trueBranch;
            }
        }

        public FamlExpression FalseBranch
        {
            get
            {
                return falseBranch;
            }
        }

 
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            sb.Append("(");
            sb.Append(condition);
            sb.Append(")?(");
            sb.Append(trueBranch);
            sb.Append("):(");
            sb.Append(falseBranch);
            sb.Append(")");
            return sb.ToString();
        }

        public override FamlExpression Expand()
        {
            // TODO: perform type compatibility check here
            return new FamlConditionalExpression(condition.Expand(),trueBranch.Expand(),falseBranch.Expand());
        }

        protected override Type ComputeType()
        {
             if (trueBranch.Type == typeof(double) && falseBranch.Type == typeof(int))
                return typeof(double); // Perform type promotion
             else if (trueBranch.Type == typeof(double) && falseBranch.Type == typeof(int))
                 return typeof(double); // Perform type promotion
             else
                 return trueBranch.Type; // TODO: check type compatibility
        }

        protected override void MakeMetadata()
        {
            int height = 1;
            int hash = NodeType.GetHashCode();

            hash ^= condition.Metadata.Hash;
            height = condition.Metadata.Height + 1;
            this.metadata.AddIfNotExist(condition.NodeParameters);

            hash ^= trueBranch.Metadata.Hash;
            height = Math.Max(height, trueBranch.Metadata.Height + 1);
            this.metadata.AddIfNotExist(trueBranch.NodeParameters);

            hash ^= falseBranch.Metadata.Hash;
            height = Math.Max(height, falseBranch.Metadata.Height + 1);
            this.metadata.AddIfNotExist(falseBranch.NodeParameters);

            this.metadata.Height = height;
            this.metadata.Hash = hash;
        }

        public override FamlExpressionType NodeType
        {
            get { return FamlExpressionType.ConditionalExpression; }
        }

        public override IEnumerable<FamlExpression> Children
        {
            get
            {
                yield return condition;
                yield return trueBranch;
                yield return falseBranch;
            }
        }
    }
}